package top.codedance.iotp.serialPortSDK.device.opw;

import top.codedance.iotp.common.util.ByteUtil;
import top.codedance.iotp.serialPortSDK.command.AokeCommand;
import top.codedance.iotp.serialPortSDK.entity.AoKeOpw;
import top.codedance.iotp.serialPortSDK.util.HexUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 澳科液位仪
 *
 * @author ChenPeng
 * @Description
 * @date 2023/4/10 10:36
 */
public class AoKe_Opw extends AbstractOpw {

    private final Map<String, List<AoKeOpw>> dataMap = new ConcurrentHashMap<>();

    private AoKe_Opw() {
    }

    public static AoKe_Opw getInstance() {
        return new AoKe_Opw();
    }

    @Override
    public String genCmdForHeightOfOil() {
        return AokeCommand.INFORMATION;
    }

    /**
     * 获取油高
     *
     * @return int
     * @Description
     * @date 2023/4/7 10:03
     */
    @Override
    public Map<String, Float> getHeightOfOil(List<String> tankNo) {
        Map<String, Float> data = new HashMap<>();
        if (!dataMap.isEmpty() && CollectionUtils.isNotEmpty(tankNo)) {
            for (String key : tankNo) {
                List<AoKeOpw> aoKeOpwList = dataMap.get(key);
                List<Float> collect = aoKeOpwList.stream().map(AoKeOpw::getVolume).collect(Collectors.toList());
                data.put(key, CollectionUtils.isEmpty(collect) ? null : collect.get(0));
            }
        }
        return data;
    }

    /**
     * 生成油水总高命令
     *
     * @return java.lang.String
     * @Description
     * @date 2023/4/7 10:03
     */
    @Override
    public String genCmdForHeight() {
        return null;
    }

    /**
     * 获取油水总高
     *
     * @return int
     * @Description
     * @date 2023/4/7 10:03
     */
    @Override
    public Map<String, Float> getHeight(List<String> tankNo) {
        Map<String, Float> data = new HashMap<>();
        if (!dataMap.isEmpty() && CollectionUtils.isNotEmpty(tankNo)) {
            for (String key : tankNo) {
                List<AoKeOpw> aoKeOpwList = dataMap.get(key);
                List<Float> collect = aoKeOpwList.stream().map(AoKeOpw::getHeight).collect(Collectors.toList());
                data.put(key, CollectionUtils.isEmpty(collect) ? null : collect.get(0));
            }
        }
        return data;
    }

    /**
     * 生成水高命令
     *
     * @return java.lang.String
     * @Description
     * @date 2023/4/7 10:04
     */
    @Override
    public String genCmdForWater() {
        return null;
    }

    /**
     * 获取水高
     *
     * @return int
     * @Description
     * @date 2023/4/7 10:04
     */
    @Override
    public Map<String, Float> getWater(List<String> tankNo) {
        Map<String, Float> data = new HashMap<>();
        if (!dataMap.isEmpty() && CollectionUtils.isNotEmpty(tankNo)) {
            for (String key : tankNo) {
                List<AoKeOpw> aoKeOpwList = dataMap.get(key);
                List<Float> collect = aoKeOpwList.stream().map(AoKeOpw::getWater).collect(Collectors.toList());
                data.put(key, CollectionUtils.isEmpty(collect) ? null : collect.get(0));
            }
        }
        return data;
    }


    /**
     * 获取油温
     *
     * @return int
     * @Description
     * @date 2023/4/7 10:04
     */
    @Override
    public Map<String, Float> getTemperature(List<String> tankNo) {
        Map<String, Float> data = new HashMap<>();
        if (!dataMap.isEmpty() && CollectionUtils.isNotEmpty(tankNo)) {
            for (String key : tankNo) {
                List<AoKeOpw> aoKeOpwList = dataMap.get(key);
                List<Float> collect = aoKeOpwList.stream().map(AoKeOpw::getTemperature).collect(Collectors.toList());
                data.put(key, CollectionUtils.isEmpty(collect) ? null : collect.get(0));
            }
        }
        return data;
    }


    /**
     * 获取水容积
     *
     * @return int
     * @Description
     * @date 2023/4/7 10:06
     */
    @Override
    public Map<String, Float> getWaterVolume(List<String> tankNo) {
        Map<String, Float> data = new HashMap<>();
        if (!dataMap.isEmpty() && CollectionUtils.isNotEmpty(tankNo)) {
            for (String key : tankNo) {
                List<AoKeOpw> aoKeOpwList = dataMap.get(key);
                List<Float> collect = aoKeOpwList.stream().map(AoKeOpw::getWaterVolume).collect(Collectors.toList());
                data.put(key, CollectionUtils.isEmpty(collect) ? null : collect.get(0));
            }
        }
        return data;
    }


    @Override
    public void parse(String result) {
        // 判断参数是否为空，为空返回异常
        if (StringUtils.isNotBlank(result)) {
            String head = result.substring(0, 8);
            switch (head) {
                // 判断获取的内容
                case AokeCommand.INFORMATION:
                    // 使用源16进制的字符串解析数据
                    this.pareWithHexStr(result);
                    break;
                default:
                    break;
            }
        }
    }

    private void pareWithHexStr(String result) {
        if (StringUtils.isNotBlank(result)) {
            // 停止位标记26 26 43 43 43 43
            String stopFlag = "26 26 43 43 43 43".replace(" ", "");
            int step = stopFlag.length();
            // 1.先计算result中有几组数据
            List<String> list = new ArrayList<>();
            String tmp = result;
            while (tmp.length() > 0) {
                int end = tmp.indexOf(stopFlag);
                end += step;
                list.add(tmp.substring(0, end));
                tmp = tmp.substring(end);
            }
            // 2.开始转换每一条数据
            this.parseOne(list);
        }
    }

    private void parseOne(List<String> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            for (String str : list) {
                // 1. 获取 i201 信息
                String head = HexUtil.hexStringToString(str.substring(0, 8));
                // 2. 获取 TT
                String globalTankName = HexUtil.hexStringToString(str.substring(8, 12));
                // 3. 获取 YYMMDDHHmm
                String time = HexUtil.hexStringToString(str.substring(12, 32));
                // 4. 获取&&
                String stopFlag = HexUtil.hexStringToString(str.substring(str.length() - 12, str.length() - 8));
                // 5. 获取CCCC
                String message = HexUtil.hexStringToString(str.substring(str.length() - 8));
                // 6.获取储罐信息
                String data = str.substring(32, str.length() - 12);
                List<String> objects = new ArrayList<>();
                int start = 0;
                while (start < data.length()) {
                    int end = start + 34;
                    objects.add(data.substring(start, end));
                    start = end;
                }
                this.parseData(objects);
            }
        }
    }

    private void parseData(List<String> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        Map<String, List<String>> map = list.stream().collect(Collectors.groupingBy(data -> data.substring(0, 4)));
        List<AoKeOpw> result = new ArrayList<>();
        for (String key : map.keySet()) {
            AoKeOpw aoKeOpw = new AoKeOpw();
            List<String> dataList = map.get(key);
            for (String str : dataList) {
                // 1.获取TT
                String tt = HexUtil.hexStringToString(str.substring(0, 4));
                aoKeOpw.setTankNumber(tt);
                // 2.获取p
                String p = HexUtil.hexStringToString(str.substring(4, 6));
                aoKeOpw.setProductCode(p);
                // 3.todo 获取ssss
                // (LSB) Delivery in Progress
                // Leak Test in Progress
                // Invaild Fuel Height Alarm (MAG Probes only)
                String ssss = HexUtil.hexStringToString(str.substring(6, 14));
                aoKeOpw.setTankStatus(ssss);
                // 4.获取NN
                Integer nn = Integer.valueOf(HexUtil.hexStringToString(str.substring(14, 18)));
                // 5. 获取FFFFFFFF
                Float ffffffff = ByteUtil.toFloat(ByteUtil.toByte(str.substring(22)));

                this.addField(aoKeOpw, nn, ffffffff);
            }
            result.add(aoKeOpw);
        }
        if (CollectionUtils.isNotEmpty(result)) {
            Map<String, List<AoKeOpw>> collect = result.stream()
                    .sorted(Comparator.comparing(AoKeOpw::getTankNumber))
                    .collect(Collectors.groupingBy(AoKeOpw::getTankNumber));
            for (String s : collect.keySet()) {
                dataMap.put(s, collect.get(s));
            }
        }

    }

    private void addField(AoKeOpw aoKeOpw, Integer nn, Float ffffffff) {
        switch (nn) {
            case 1:
                aoKeOpw.setVolume(ffffffff);
                break;
            case 2:
                aoKeOpw.setTcVolume(ffffffff);
                break;
            case 3:
                aoKeOpw.setUllage(ffffffff);
                break;
            case 4:
                aoKeOpw.setHeight(ffffffff);
                break;
            case 5:
                aoKeOpw.setWater(ffffffff);
                break;
            case 6:
                aoKeOpw.setTemperature(ffffffff);
                break;
            case 7:
                aoKeOpw.setWaterVolume(ffffffff);
                break;
            default:
                break;
        }
    }

}
